package com.itany.nmms.factory;

import com.itany.nmms.exception.ObjectFactoryErrorException;
import com.itany.nmms.util.MyBatisUtil;
import com.itany.nmms.util.ParameterUtil;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

/**
 * Author:shixiaojun@itany.com
 * Date:2022/4/27 15:02
 * Version:1.0-SNAPSHOT
 * Description:
 */
public class ObjectFactory {

    private static Map<String,Object> objs;

    static{
        objs = new HashMap<>();
        BufferedReader br = null;
        try {
            br = new BufferedReader(
                    new InputStreamReader(
                            ObjectFactory
                                    .class
                                    .getClassLoader()
                                    .getResourceAsStream("beans.properties")));
            String line = null;
            while((line = br.readLine()) != null){
                // 防止读取到空行
                if(!ParameterUtil.isNull(line)){
                    // 通过等号进行分割,分割成数组
                    String[] arr = line.split("=");
                    // 第一个元素为key
                    String key = arr[0];
                    // 第二个元素为value
                    String value = arr[1];
                    // 对于dao与其他的bean获取方式不一致
                    // dao配置的是接口,而其他配置的实现类
                    // dao接口需要通过SqlSession获取到对应的代理对象
                    // 而SqlSession在处理时同一个业务属于同一个SqlSession
                    // 不同的业务的SqlSession不一致
                    // 因此,dao的获取必须在SqlSession中
                    // 此处不适合获取dao
                    // 此处只处理dao以外的bean
                    // 获取当前value所对应的bean的Class类型
                    Class target = Class.forName(value);
                    // 判断当前的bean是否是接口
                    if(target.isInterface()){
                        // 如果当前的bean是接口,则可以直接将Class进行存储
                        // 不需要实例化
                        objs.put(key,target);
                        continue;
                    }
                    // 如果不是dao接口,则进行实例化
                    // 将实例化后的bean进行存储
                    objs.put(key,target.newInstance());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new ExceptionInInitializerError("ObjectFactory初始化失败");
        } finally {
            if(br != null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    throw new ExceptionInInitializerError("ObjectFactory初始化失败");
                }
            }
        }
    }

    public static Object getObject(String key){
        // 该方法会在使用时调用
        // 因此,需要在此处获取dao所对应的代理对象
        // 判断当前是否是dao接口
        Object obj = objs.get(key);
        // 如果没有获取到对象,给出错误提示
        if(null == obj){
            throw new ObjectFactoryErrorException("根据对应的key:"+key+"在配置文件中没有找到对应的配置");
        }
        // 由于当前存储的所有bean中只有dao存储的是Class
        // 因此,如果获取的对象是Class类型,则表示是dao接口
        if(obj instanceof Class){
            // 获取dao对应的代理对象并返回
            return MyBatisUtil.getSession().getMapper((Class)obj);
        }
        // 如果不是dao接口,直接返回
        return obj;
    }
}
